/*
 * AuthorCategoryDict.cpp
 *
 *  Created on: Sep 20, 2011
 *      Author: srihari
 */

#include "AuthorCategoryDict.h"
using namespace std;

AuthorCategoryDict* AuthorCategoryDict::instance = 0;

AuthorCategoryDict* AuthorCategoryDict::getInstance() {
	if (!AuthorCategoryDict::instance) {
		AuthorCategoryDict::instance = new AuthorCategoryDict();
	}
	return AuthorCategoryDict::instance;
}

AuthorCategoryDict::AuthorCategoryDict() {
	config* configInstance = config::getInstance();
	dirPath = configInstance->getValue("path_to_dict_store_dir");

	nextAuthId = 1;
	nextCatId = 1;
	// string authorPath = dirPath + "/auth_dict.txt";
	// string categoryPath = dirPath + "/cat_dict.txt";
	string linkPath = dirPath + "/link_pair_repo.txt";
	// authorStream.open(authorPath.c_str());
	// categoryStream.open(categoryPath.c_str());
	linkStream.open(linkPath.c_str());
	/* if (!authorStream.is_open()) {
	 cout << "Author Dict Failure";
	 }
	 if (!categoryStream.is_open()) {
	 cout << "Category Dict Failure";
	 }*/

	if (!linkStream.is_open()) {
		cout << "Link Repo Failure";
	}
}

AuthorCategoryDict::~AuthorCategoryDict() {
	// TODO Auto-generated destructor stub
}

size_t AuthorCategoryDict::addAuthor(string author) {
	pair<map<string, size_t>::iterator, bool> ret;
	ret = authorMap.insert(pair<string, size_t>(author, nextAuthId));
	if (!ret.second) {
		return ret.first->second;
	}
	nextAuthId++;
	return (nextAuthId - 1);
}

size_t AuthorCategoryDict::addCategory(string category) {
	pair<map<string, size_t>::iterator, bool> ret;
	ret = categoryMap.insert(pair<string, size_t>(category, nextCatId));
	if (!ret.second) {
		return ret.first->second;
	}
	nextCatId++;
	return (nextCatId - 1);
}

void AuthorCategoryDict::insertAuthorToFileMap(size_t aid, size_t fid) {
	pair<map<size_t, string>::iterator, bool> ret;
	cout << aid;
	ret = authorTOFileMap.insert(pair<size_t, string>(fid, CUtilities::number_to_string(aid)));
	if ( !ret.second ) {
		ret.first->second += ",";
		ret.first->second += CUtilities::number_to_string(aid);
		cout << "==================>" <<ret.first->second << endl;
	}
}

string AuthorCategoryDict::getAuthorByFileID(size_t fid) {
	map<size_t, string>::iterator it = this->authorTOFileMap.find(fid);
	if (it != this->authorTOFileMap.end() ) {
		return it->second;
	} else {
		return "";
	}
}

void AuthorCategoryDict::addLinkPair(string source, string destination) {
	//cout << "start to write auth dict file." << endl;
	if (linkStream.is_open()) {
		if (!destination.empty()) {
			linkStream << source << "," << destination << endl;
		}
	}
}

void AuthorCategoryDict::writeToDisk() {
	string authorPath = dirPath + "/auth_dict.txt";
	string catPath = dirPath + "/cat_dict.txt";
	authorStream.open(authorPath.c_str());
	categoryStream.open(catPath.c_str());
	map<string, size_t>::iterator iter;

	// Write Author Dict
	for (iter = authorMap.begin(); iter != authorMap.end(); iter++) {
		authorStream << iter->second << ":" << iter->first << endl;
	}
	authorMap.clear();
	authorStream.close();

	// Write Category Dict
	for (iter = categoryMap.begin(); iter != categoryMap.end(); iter++) {
		categoryStream << iter->second << ":" << iter->first << endl;
	}
	categoryMap.clear();
	categoryStream.close();

	// Links
	linkStream.close();
}

void AuthorCategoryDict::constructLinkDict(std::map<string, size_t> fileNameIdMap) {
	ifstream linkInpRepoStream;
	ofstream linkDictStream;
	string linkInpRepo = dirPath + "/link_pair_repo.txt";
	string linkDict = dirPath + "/link_dict.txt";

	// Init streams
	linkInpRepoStream.open(linkInpRepo.c_str());
	if (!linkInpRepoStream.is_open()) {
		cout << "Error reading Link Repo";
		return;
	}
	linkDictStream.open(linkDict.c_str());
	if (!linkDictStream.is_open()) {
		cout << "Error writing Link Dict";
		return;
	}

	string currLine;
	size_t srcFileId;
	size_t destFileId;
	cout << "fileNameIdMap size" << fileNameIdMap.size() << endl;
	while (linkInpRepoStream.good()) {
		getline(linkInpRepoStream, currLine);
		vector<string> temp;
		CUtilities::tokenize(currLine, temp, ",");
		if (temp.size() < 2 || temp[0].size() == 0 || temp[1].size() < 3)
			continue;
		CUtilities::trim_left_right(temp[0]);
		CUtilities::trim_left_right(temp[1]);
		CUtilities::to_lower(temp[0]);
		CUtilities::to_lower(temp[1]);
		replace(temp[1].begin(), temp[1].end() - 1, ' ', '_');

		// Handle | char
		vector<string> temp1;
		CUtilities::tokenize(temp[1], temp1, "|");
		temp[1] = temp1[0];

		map<string, size_t>::iterator iter = fileNameIdMap.find(temp[1]);
		if (iter != fileNameIdMap.end()) {
			destFileId = iter->second;
			// cout << "Dest File Id:" << destFileId << endl;

			iter = fileNameIdMap.find(temp[0]);
			if (iter != fileNameIdMap.end()) {
				srcFileId = iter->second;
				string authorA = getAuthorByFileID(srcFileId);
				string authorB = getAuthorByFileID(destFileId);
				linkDictStream << srcFileId << ":" << destFileId << ":"<< authorA << ":"<< authorB << endl;
				// insertIntoLinkDict(srcFileId, destFileId);
			}
		}
	}
	linkInpRepoStream.close();

	// Write Link Dict
	/*map<size_t, string>::iterator iter;
	 for (iter=linkDictMap.begin(); iter != linkDictMap.end(); iter++) {
	 linkDictStream << iter->first << ":" << iter->second << endl;
	 }*/
	linkDictStream.close();
}

void AuthorCategoryDict::insertIntoLinkDict(size_t srcFileId, size_t destFileId) {
	pair<map<size_t, string>::iterator, bool> ret;
	// string destFileIdStr = "";
	// destFileIdStr = CUtilities::number_to_string(destFileId);
	// destFileIdStr += CUtilities::number_to_string(destFileId));
	//ret = linkDictMap.insert(pair<size_t, string>(srcFileId, destFileIdStr));
	//if (false == ret.second) {
	// cout << "Src Dest" << srcFileId << " " << destFileId << endl;
	//	linkDictStream << srcFileId << ":" << destFileId << endl;
	//	linkDictMap[srcFileId] += " " + destFileIdStr;
	//	cout << "Src Dest" << srcFileId << " " << destFileIdStr << endl;
	// }
}
